/**
 * 
 */
package archsw0904.controller.shopping.order;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.jws.WebService;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.NameValuePair;

import archsw0904.controller.registration.NullMandatoryFieldException;
import archsw0904.controller.shopping.cart.InvalidCartException;
import archsw0904.controller.shopping.common.BookListVisualizationInfo;
import archsw0904.controller.shopping.common.CartException;
import archsw0904.controller.shopping.common.Http;
import archsw0904.model.Authenticated;
import archsw0904.model.Book;
import archsw0904.model.Cart;
import archsw0904.model.OrderStatus;
import archsw0904.model.OrderedCopies;
import archsw0904.model.Orders;
import archsw0904.model.ProfileClient;

/**
 * @author ASGroup0904
 *
 */

@Stateless
@WebService
public class OrderBean {

	private static final String ORDER_ID_FIELD_NAME = "orderId";

	private static final String TOTAL_FIELD_NAME = "total";
	
	@PersistenceContext
    private EntityManager em;
	
	@Resource
	private String paymentSystemURI;
	
	public Cart findCart(Integer id) throws InvalidCartException{
		Cart cart; 
		
		cart=em.find(Cart.class, id);
		
		if(cart==null){
			throw new InvalidCartException();
		}
		if(cart.getCartLines().isEmpty()){
			throw new InvalidCartException();
		}
		
		return cart;
	}
	
	public Orders createOrder(Integer clientId,String name, String surname, String address, String cap, String city, String state) throws archsw0904.controller.registration.NullMandatoryFieldException, InvalidCartException, HttpException, IOException {
		Cart cart;
		Orders order;
		Date oldDate;
		
		System.out.println("createOrder");
		cart=getCart(clientId);
		
		oldDate=cart.getDate();
		
		checkHomeDelivery(name,surname,address,cap,city,state);
		order= new Orders();
		order.setDate(new GregorianCalendar().getTime());
		order.setClient(cart.getClient());
		order.setBookList(cart.getCartLines());
		order.setTotal(cart.getTotal());
		order.setStatus(OrderStatus.Open);
		order.setDeliveryAddress(address);
		order.setDeliveryCap(cap);
		order.setDeliveryCity(city);
		order.setDeliveryName(name);
		order.setDeliverySurname(surname);
		order.setState(state);
		order.setBookList(cart.getCartLines());  //AGGIUNTA
		em.persist(order);
		//pulizia carrello
		cart.setCartLines(new HashMap<Book,OrderedCopies>());
		cart.setDate(null);
		cart.setTotal(new BigDecimal(0));
		em.persist(cart);
		
		em.flush();

		try{
		Http.post(paymentSystemURI, 
					new NameValuePair(ORDER_ID_FIELD_NAME,order.getId().toString()),
					new NameValuePair(TOTAL_FIELD_NAME,order.getTotal().toString()));
		}catch(Exception e){
			System.out.println("non ho postato niente");
			cart.setDate(oldDate);
			cart.setTotal(order.getTotal());
			cart.setCartLines(order.getBookList());
			em.persist(cart);
			em.remove(order);
			em.flush();	
			throw new IOException();
		}
		
		return order;
	}
	
	
	
	
	public void checkHomeDelivery(String name, String surname, String address, String cap, String city, String state) throws archsw0904.controller.registration.NullMandatoryFieldException{
		mandatoryNullFieldCheck(name, surname, address, cap, city, state);
		nameCheck(name,surname,city,state);
		capCheck(cap);
		
	}
	
	private void mandatoryNullFieldCheck(String name, String surname, String address, String cap, String city, String state) throws NullMandatoryFieldException {
		
		mandatoryNull(name, "name");
		mandatoryNull(surname, "surname");
		mandatoryNull(address, "address");
		mandatoryNull(cap, "cap");
		mandatoryNull(city, "city");
		mandatoryNull(state, "state");
	}
	
	private void mandatoryNull(String field,String name) throws NullMandatoryFieldException{
		if(field==null ) {
			throw new NullMandatoryFieldException(name + " is empty, obligatory field");
		}
		if (field.isEmpty()) throw new NullMandatoryFieldException(name+ " is empty, obligatory field"); 
	}
	
	private void nameCheck(String name, String surname, String city, String state) throws NullMandatoryFieldException {
		//Pattern p =Pattern.compile("[A-Za-z' ]+");
		Pattern p =Pattern.compile(".*[1-9].*");
		Matcher m;
		boolean matchFound ;
		if (name!=null){ 
			m = p.matcher(name);
			matchFound = m.matches();
			if (matchFound)
				throw new NullMandatoryFieldException("name format not correct "+ name) ;	
		}
		if (name!=null){
			m = p.matcher(surname);
			matchFound = m.matches();
			if (matchFound)
				throw new NullMandatoryFieldException("surname format not correct "+ surname) ;
		}
		if (name!=null){	
			m = p.matcher(city);
			matchFound = m.matches();
			if (matchFound&&!(city.isEmpty()))
				throw new NullMandatoryFieldException("city format not correct"+ city) ; 	
		}
		if (name!=null){	
			m = p.matcher(state);
			matchFound = m.matches();
			if (matchFound&&!(state.isEmpty()))
				throw new NullMandatoryFieldException("state format not correct"+ state) ; 	
		}
	}
	private void capCheck(String cap)throws NullMandatoryFieldException{
		Pattern p = Pattern.compile("[0-9]*");
		Matcher m;
		boolean matchFound ;
		if (cap!=null){
			m = p.matcher(cap);
			matchFound = m.matches();
			if (!matchFound)
				throw new NullMandatoryFieldException("cap format not correct "+ cap) ;	
		}	
		
	}
	private Cart getCart(Integer idClient) throws InvalidCartException{
		ProfileClient pc ;
		Cart cart = null;
		Query q ;
		q= em.createQuery("SELECT OBJECT(obj) FROM ProfileClient obj WHERE obj.id = " + idClient.toString() );
		if ( q == null ) {
			System.out.print("cart1111)");
			System.out.flush();
			throw new InvalidCartException();
		} else {
			try {
				pc = (ProfileClient) q.getSingleResult() ;
				System.out.print("cart2222)");
				System.out.flush();
				if ( !pc.getId().equals(idClient) ) throw new InvalidCartException();
			} catch (NoResultException e) {
				System.out.print("cart333)");
				System.out.flush();
				throw new InvalidCartException();
				}
		}
		q = em.createQuery("SELECT OBJECT(obj) FROM Cart obj WHERE obj.client = " + idClient.toString() );
		if ( q != null ) {
			if ( !q.getResultList().isEmpty() ) {
				cart = (Cart) q.getSingleResult() ;
				System.out.print("cart4444)");
				System.out.flush();
				if ( cart == null ) throw new InvalidCartException() ;
				if(cart.getCartLines().isEmpty()) throw new InvalidCartException() ;
			}
		}
		return cart;
	}
	
	@SuppressWarnings("unchecked")
	public int  getBookList ( Integer clientId ) throws CartException {
		Orders ordine=null;
		Query q ;
		BookListVisualizationInfo [] result = new BookListVisualizationInfo[0];
		ArrayList<BookListVisualizationInfo> bookListInfo = new ArrayList<BookListVisualizationInfo>();
		Authenticated auth = em.find( Authenticated.class, new Integer(clientId));
		ProfileClient client =null;
		if (auth!=null){
			client = em.find(ProfileClient.class, auth.getUser().getId());
		}
		q= em.createQuery("SELECT OBJECT(obj) FROM Orders obj WHERE obj.client.id = " + client.getId() );
		ArrayList<Orders> orderListInfo =  (ArrayList<Orders>) q.getResultList();
		for (int i=0; i<orderListInfo.size(); i++){
			ordine = orderListInfo.get(i);
			BookListVisualizationInfo cInfo = new BookListVisualizationInfo () ;
			cInfo.setTotalPrice(ordine.getTotal()) ;
			
			Map<Book,OrderedCopies> mapList = ordine.getBookList();
			
			for ( Book book : mapList.keySet() ) {
				cInfo.addBook(book, mapList.get(book).getNumberOfCopies() ) ;
			}
			bookListInfo.add(cInfo);
		}
		bookListInfo.toArray(result);
		return 0;
	}
	
	@SuppressWarnings("unchecked")
	public OrderView[] getOrderView(Integer clientId) {
		Orders ordine=null;
		Query q ;
		ArrayList<OrderView> listOrder = new ArrayList<OrderView>();
		ProfileClient pc = null;
		Authenticated auth = em.find( Authenticated.class, new Integer(clientId));
		if (auth!=null){
			pc = em.find(ProfileClient.class, auth.getUser().getId());
		}
		System.out.print(pc.getId().toString());
		OrderView[] result = new OrderView[0];
		System.out.print(pc.getCap());
		q= em.createQuery("SELECT OBJECT(obj) FROM Orders obj WHERE obj.client.id = " + pc.getId().toString() );
		List<Orders> orderListInfo =  (List<Orders>) q.getResultList();
		for (int i=0; i<orderListInfo.size(); i++){
			ordine = orderListInfo.get(i);
			if (ordine.getStatus()!=OrderStatus.Cancelled){
				BookListVisualizationInfo cInfo = new BookListVisualizationInfo () ;
				OrderView orderView = new OrderView();
				cInfo.setTotalPrice(ordine.getTotal()) ;
				
				Map<Book,OrderedCopies> mapList = ordine.getBookList();
				
				for ( Book book : mapList.keySet() ) {
					System.out.print("dentro il for di orderBean");
					cInfo.addBook(book, mapList.get(book).getNumberOfCopies() ) ;
				}
				
				orderView.setBookInfo(cInfo.getBookList());
				orderView.setTotalPrice(ordine.getTotal());
				orderView.setDate(ordine.getDate());
				orderView.setDeliveryAddress(ordine.getDeliveryAddress());
				orderView.setDeliveryCap(ordine.getDeliveryCap());
				orderView.setDeliveryCity(ordine.getDeliveryCity());
				orderView.setDeliveryCode(ordine.getDeliveryCode());
				orderView.setDeliveryName(ordine.getDeliveryName());
				orderView.setDeliverySurname(ordine.getDeliverySurname());
				orderView.setState(ordine.getState());
				orderView.setStatus(ordine.getStatus());
				orderView.setOrderId(ordine.getId());
				System.out.print("orderbean " + orderView.getBookInfo().length); 
				listOrder.add(orderView);	
			}
		}
		result = listOrder.toArray(result);
		return result;
	}
	
}
